﻿#region Copyright Jonathan Quiros

//	
// All rights are reserved. Reproduction or transmission in whole or in 
// part, in any form or by any means, electronic, mechanical or otherwise, 
// is prohibited without the prior written consent of the copyright owner.
//
// Filename: SmtpEmailSender.cs
//

#endregion

using System.Collections.Generic;
using System.Linq;
using System.Net.Mail;
using System.Net.Mime;
using System.Text;

namespace Novagoal.Utils.Implementations
{
    public class SmtpEmailSender : IEmailSender
    {
        private readonly MailCredential _defaultCredential;

        /// <summary>
        /// Initializes a new instance of the <see cref="SmtpEmailSender"/> class.
        /// </summary>
        /// <param name="server">The server.</param>
        /// <param name="account">The account.</param>
        /// <param name="password">The password.</param>
        /// <param name="usesSsl">if set to <c>true</c> [uses SSL].</param>
        public SmtpEmailSender(string server, string account, string password, bool usesSsl)
        {
            _defaultCredential = new MailCredential
            {
                Server = server,
                Account = account,
                Password = password,
            };
            UsesSsl = usesSsl;
        }

        /// <summary>
        /// Gets or sets a value indicating whether [uses SSL].
        /// </summary>
        /// <value><c>true</c> if [uses SSL]; otherwise, <c>false</c>.</value>
        public bool UsesSsl { get; set; }

        /// <summary>
        /// Sends an email.
        /// </summary>
        /// <param name="givenCredential">The mail credential.</param>
        /// <param name="toEmail"> A <c>System.String</c> that contains the addresses of the recipients of the e-mail message.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="html">The HTML.</param>
        public void SendEmail(MailCredential givenCredential, string toEmail, string subject, string html)
        {
            var credential = givenCredential ?? _defaultCredential;
            SendEmail(credential, toEmail, subject, html, Enumerable.Empty<string>());
        }

        /// <summary>
        /// Sends the email.
        /// </summary>
        /// <param name="givenCredential">The given credential.</param>
        /// <param name="toEmails"> A <c>System.String</c> that contains the addresses of the recipients of the e-mail message.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="html">The HTML.</param>
        /// <param name="attachments">The attachments.</param>
        public void SendEmail(MailCredential givenCredential, string toEmails, string subject, string html, IEnumerable<string> attachments)
        {
            var credential = givenCredential ?? _defaultCredential;
            using (var msg = GetMailMessage(credential, toEmails, subject, html))
            {
                SendEmail(credential, msg, attachments);
            }
        }

        public void SendEmail(MailCredential givenCredential, EmailTask emailTask)
        {
            var credential = givenCredential ?? _defaultCredential;
            using (var msg = GetMailMessage(credential, emailTask.ToEmail, emailTask.Subject, emailTask.Html))
            {
                SendEmail(credential, msg, emailTask.Attachments);
            }
        }

        /// <summary>
        /// Sends the email.
        /// </summary>
        /// <param name="givenCredential">The given credential.</param>
        /// <param name="toEmails"> A <c>System.String</c> that contains the addresses of the recipients of the e-mail message.</param>
        /// <param name="carbonCopyEmails">The cc emails.</param>
        /// <param name="blindCarbonCopyEmails">The BCC emails.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="html">The HTML.</param>
        /// <param name="attachments">The attachments.</param>
        public void SendEmail(MailCredential givenCredential, string toEmails, string carbonCopyEmails, string blindCarbonCopyEmails, string subject, string html, IEnumerable<string> attachments)
        {
            var credential = givenCredential ?? _defaultCredential;
            using (var msg = GetMailMessage(credential, toEmails, subject, html, carbonCopyEmails, blindCarbonCopyEmails))
            {
                SendEmail(credential, msg, attachments);
            }
        }

        /// <summary>
        /// Sends the email using the given credential.
        /// </summary>
        /// <param name="credential">The credential.</param>
        /// <param name="message">The message.</param>
        /// <param name="attachments">The attachments.</param>
        private void SendEmail(MailCredential credential, MailMessage message, IEnumerable<string> attachments)
        {
            foreach (var attach in attachments)
            {
                var attached = new Attachment(attach, MediaTypeNames.Application.Octet);
                message.Attachments.Add(attached);
            }
            var client = new SmtpClient
            {
                Credentials = new System.Net.NetworkCredential(credential.Account, credential.Password),
                Host = credential.Server,
                EnableSsl = UsesSsl,
            };
            client.Send(message);
        }

        /// <summary>
        /// Gets a mail message.
        /// </summary>
        /// <param name="credential">The credential.</param>
        /// <param name="toEmail"> A <c>System.String</c> that contains the addresses of the recipient of the e-mail message.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="html">The HTML.</param>
        /// <returns>A <see cref="MailMessage"/></returns>
        private static MailMessage GetMailMessage(MailCredential credential, string toEmail, string subject, string html)
        {
            return new MailMessage(credential.Account, toEmail)
            {
                Subject = subject,
                SubjectEncoding = Encoding.UTF8,
                Body = html,
                BodyEncoding = Encoding.UTF8,
                IsBodyHtml = true,
                Priority = MailPriority.Normal,
            };
        }

        /// <summary>
        /// Gets a mail message.
        /// </summary>
        /// <param name="credential">The credential.</param>
        /// <param name="toEmail"> A <c>System.String</c> that contains the addresses of the recipient of the e-mail message.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="html">The HTML.</param>
        /// <param name="cc">The cc.</param>
        /// <param name="bcc">The BCC.</param>
        /// <returns>A <see cref="MailMessage"/></returns>
        private static MailMessage GetMailMessage(MailCredential credential, string toEmail, string subject, string html, string cc, string bcc)
        {
            var mailMessage = new MailMessage(credential.Account, toEmail)
            {

                Subject = subject,
                SubjectEncoding = Encoding.UTF8,
                Body = html,
                BodyEncoding = Encoding.UTF8,
                IsBodyHtml = true,
                Priority = MailPriority.Normal,
            };
            if (!string.IsNullOrEmpty(cc))
            {
                mailMessage.CC.Add(cc);
            }
            if (!string.IsNullOrEmpty(bcc))
            {
                mailMessage.Bcc.Add(bcc);
            }
            return mailMessage;
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            //do nothing
        }
    }
}
